/*
 * shoutcast.c
 *
 * Created: 2011-11-19 19:17:07
 *  Author: krzychu
 */ 
#include "types.h"
#include "vs.h"
#include "eeprom_fifo.h"
#include "ethernet.h"
#include "shoutcast.h"
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <string.h>

volatile byte	shout_status;
UINT16			shout_localport=0x0000;
UINT32			shout_timeout;
byte			shout_try;
byte			*shout_data;
char			shout_stationName[20];/* lcd size restricted */
UINT16			shout_datlen;
byte			shout_station;

//shout_status = SHOUTCAST_CLOSED;

void	Shoutcast_Close(void)
{
	if( shout_status != SHOUTCAST_CLOSED )
	{
		shout_status = SHOUTCAST_CLOSED;
		//shout_timeout = get_acttime() + SHOUTCAST_TIMEOUT;
	}
	
	return;
}	

void	Shoutcast_Open(byte index)
{
	IP_addr ip_addr;
	UINT16	port;
	byte	url[33];
	
	shout_station = index;
	
	Shoutcast_StationName( shout_station, shout_stationName );
	Shoutcast_StationAddr( shout_station, &ip_addr, &port, url);
	
	TCP_Open( ARP_GetMac(&ip_addr), &ip_addr, port, 8001);
	
	shout_status = SHOUTCAST_OPEN;
	shout_timeout = get_acttime() + SHOUTCAST_TIMEOUT;
	
	return;
}

UINT16	Shoutcast_Data(byte inx, byte *d, UINT16 len, byte *out)
{
	UINT16	length;
	IP_addr	ip_addr;
	UINT16	port;
	byte	url[33];
	
	length = 0x0000;
	
	shout_timeout = get_acttime() + SHOUTCAST_TIMEOUT;
	
	switch( shout_status )
	{
		case SHOUTCAST_OPEN:
			Shoutcast_StationAddr( shout_station, &ip_addr, &port, url);
			length = sprintf_P((char*)out, PSTR(	"GET %s HTTP/1.0\r\n"
											"Host: %i.%i.%i.%i\r\n"
											"Accept: */*\r\n"
											"Icy-MetaData: 0\r\n"
											"Connection: Keep-Alive\r\n"
											"\r\n"),
											url, ip_addr.b8[0],ip_addr.b8[1], ip_addr.b8[2],ip_addr.b8[3]);
			
			shout_status = SHOUTCAST_HEADER;
		break;
		
		case SHOUTCAST_OPENED:
			if( len )
			{
				shout_data = d;
				shout_datlen = len;
			}
		break;
		
		case SHOUTCAST_BUFFER:
			if( len )
			{
				if ( ((d[0] == 'I') && (d[1] == 'C') && (d[2] == 'Y') )||
					 ((d[0] == 'H') && (d[1] == 'T') && (d[2] == 'T') && (d[3] == 'P')))
				{
					for(; len != 0; len--)
					{
						d++;
						
						if ( (d[0] == '\r') && (d[1] == '\n') && (d[2] == '\r') && (d[3] == '\n') )
						{
							len = len - 0x0004;
							d = d + 4;
							break;
						}
					}
				}
				
				shout_datlen = len;
				shout_data	= d;
			}
		break;
		
		case SHOUTCAST_CLOSE:
			TCP_Abort(inx);
			VS1053_SoftReset();
			shout_status = SHOUTCAST_CLOSED;
			shout_try = SHOUTCAST_TRY;
		break;
		
		case SHOUTCAST_CLOSED:
		break;
		
		case SHOUTCAST_HEADER:
			shout_status = SHOUTCAST_BUFFER;
		break;
	}
	
	return length;
}

void	Shoutcast_Service()
{
	byte len;
	byte *point, b[32];
	point = shout_data;
	len = 128;
	
	switch( shout_status )
	{
		case SHOUTCAST_OPEN:
			if ( (get_acttime() - shout_timeout) > 0 )
			{
				if (shout_try)
				{
					shout_try--;
					Shoutcast_Open( shout_station );
				}
				else
				{
					Shoutcast_Close();
				}
				return;
			}
		break;
		
		case SHOUTCAST_OPENED:
		if ( fifo_buffer() < SHOUTCAST_BUFF_MIN )
		{
			fifo_put( shout_data, shout_datlen );
			shout_datlen = 0x0000;
			
			shout_status = SHOUTCAST_BUFFER;
		}
		else
		{
			do 
			{
				if ( VS_DREQ_CHECK() ) /* send data to the VS, if possible */
				{
					if( fifo_pop32b(b) == 0)
					{
						VS1053_Data32(b);
					}
					
				}
				
				if( fifo_free() >= len )
				{
					if ( shout_datlen > len )
					{
						wdt_reset();
						fifo_put(point, len);
						point = point + len;
						shout_datlen = shout_datlen - len;
					}
					else if ( shout_datlen > 0)
					{
						wdt_reset();
						fifo_put( point, shout_datlen);
						shout_datlen = 0x0000;
					}
				}
			} while ( shout_datlen );
		}			
			
		break;
		
		case SHOUTCAST_BUFFER:
			fifo_put( shout_data, shout_datlen);
			shout_datlen = 0x0000;

			if( fifo_buffer() > SHOUTCAST_BUFF_PLAY)
			{
				shout_status = SHOUTCAST_OPENED;
			}
		break;
		
		case SHOUTCAST_CLOSE:
			if( (get_acttime() - shout_timeout) > 0)
			{
				VS1053_SoftReset();
				shout_status = SHOUTCAST_CLOSED;
				shout_try = SHOUTCAST_TRY;
			}
		break;
		
		case SHOUTCAST_CLOSED:
			
		break;
	}
}
void	Shoutcast_StationAddr(byte index, IP_addr* ip_addr, UINT16 *port, byte *url)
{
	char ipaddr[32];
	char *ptr;
	
	ptr = &ipaddr[0];
	
	if ( index < 5)
	{
		switch( index )
		{
			case 0:
				strcpy_P( ipaddr, PSTR("217.74.72.2:9000/"));	// RMF FM
			break;
		}
	}
	
	if(isdigit(*ptr))	// ip
	{
		ip_addr->b8[0]	=	atoi(ptr);
		while( isdigit(*ptr) ){ ptr++; }; // move to the next char and check whether isdigit
		while( !isdigit(*ptr)){ ptr++; }; // skip non digit char
		ip_addr->b8[1]	=	atoi(ptr);
		while( isdigit(*ptr) ){ ptr++; }; // move to the next char and check whether isdigit
		while( !isdigit(*ptr)){ ptr++; }; // skip non digit char
		ip_addr->b8[2]	=	atoi(ptr);
		while( isdigit(*ptr) ){ ptr++; }; // move to the next char and check whehter isdigit
		while( !isdigit(*ptr)){ ptr++; }; // skip non digit char
		ip_addr->b8[3]	=	atoi(ptr);
		while( isdigit(*ptr) ){ ptr++; }; // move to the next char and check whehter isdigit
		while( !isdigit(*ptr)){ ptr++; }; // skip non digit char
	}
	else	// url
	{
		// DNS resolve...
	}
	
	*port	=	atoi(ptr);
	while ( isdigit(*ptr) ){ ptr++; };
		
	if( *ptr == 0 )
	{
		*url++	=	'/';
		*url	=	0;
	}
	else
	{
		while ( *ptr )
		{
			if ( *ptr == ' ' )
			{
				*url++	=	*ptr;
				*url	=	0;
			}
			ptr++;
		}
	}
	
	return;
}

void	Shoutcast_StationName( byte index, char *name)
{
	if ( index < 5 )
	{
		switch ( index )
		{
			case 0:
				strcpy_P( name, PSTR("RMF FM") );
			break;
		}
	}
	
	return;
}